/**
 * this class handle de CRUD operations in mongo db for Establishments
 */
package co.edu.unal.satacredito.database.dao;

import co.edu.unal.satacredito.database.entity.Brand;
import co.edu.unal.satacredito.database.entity.Establishment;
import co.edu.unal.satacredito.database.entity.exceptions.NonexistentEntityException;
import co.edu.unal.satacredito.database.entity.exceptions.NullFieldEntityException;
import co.edu.unal.satacredito.database.entity.exceptions.PreexistingEntityException;
import com.google.code.morphia.Datastore;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import java.util.List;
import org.bson.types.ObjectId;

/**
 *
 * @author Miguel Alexander Diaz 257835
 */
public class EstablishmentMongoDao {
    
    private Datastore ds = null;
    
    public EstablishmentMongoDao(Datastore ds) {
        this.ds = ds;
        this.ds.ensureIndexes();
    }
    
    public Datastore getDatastore() {
        return ds;
    }
    
    public void create(Establishment establishment) throws PreexistingEntityException {
        try {
            ds.save(establishment);
        } catch (Exception e) {
            throw new PreexistingEntityException("The establishment with name "
                    + establishment.getNameEstablishment() + "couldn't be created. Already exist.");
        }
    }
    
    public void update(ObjectId id, Establishment newestablishment) throws
            NonexistentEntityException, PreexistingEntityException, NullFieldEntityException, Exception {
        try {
            Query q = ds.createQuery(Establishment.class).field("_id").equal(id);
            UpdateOperations<Establishment> ops = null;
            try {
                ops = ds.createUpdateOperations(Establishment.class).set("user", newestablishment.getUser()).set("password", newestablishment.getPassword()).set("nameEstablishment", newestablishment.getNameEstablishment()).set("phoneNumber", newestablishment.getPhoneNumber()).set("managerFirstName", newestablishment.getManagerFirstName()).set("managerLastName", newestablishment.getManagerLastName()).set("managerId", newestablishment.getManagerId()).set("email", newestablishment.getEmail()).set("brand", newestablishment.getBrand()).set("status", newestablishment.getStatus());
            } catch (Exception e) {
                throw new NullFieldEntityException("the Administrator with id '"
                        + id.toString() + "' have null fields.");
            }
            ds.update(q, ops);
        } catch (Exception e) {
            if (e.getClass().getSimpleName().equals("DuplicateKey")) {
                throw new PreexistingEntityException(e.getMessage());
            } else if (e.getClass().equals(NullFieldEntityException.class)) {
                throw e;
            } else {
                throw new NonexistentEntityException("The establishment with id '"
                        + id.toString() + "' couldn't be updated. May no longer exist");
            }
        }
    }
    
    public void delete(ObjectId id) throws NonexistentEntityException {
        try {
            Query q = ds.createQuery(Establishment.class).field("_id").equal(id);
            ds.delete(q);
        } catch (Exception e) {
            throw new NonexistentEntityException("The establishment with the id '"
                    + id.toString() + "' couldn't be deleted. May no longer exist.");
        }
    }
    
    public List<Establishment> findAll() throws NonexistentEntityException {
        try {
            List<Establishment> list = ds.find(Establishment.class).asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any element of the 'Establishment' type ");
        }
    }
    
    public Establishment findByUser(String user) throws NonexistentEntityException, Exception {
        try {
            Query q = ds.createQuery(Establishment.class).field("user").equal(user);
            if (q.countAll() == 0) {
                throw new NonexistentEntityException("The establishment with user '"
                        + user + "' couldn't be find. May no longer exist");
            } else {
                Establishment ad = (Establishment) q.get();
                return ad;
            }
        } catch (Exception e) {
            throw e;
        }
    }
    
    public Establishment findByNameEstablishment(String nameEstablishment) throws NonexistentEntityException, Exception {
        try {
            Query q = ds.createQuery(Establishment.class).field("nameEstablishment").equal(nameEstablishment);
            if (q.countAll() == 0) {
                throw new NonexistentEntityException("The establishment with name '"
                        + nameEstablishment + "' couldn't be find. May no longer exist");
            } else {
                Establishment ad = (Establishment) q.get();
                return ad;
            }
        } catch (Exception e) {
            throw e;
        }
    }
    
    public List<Establishment> findByBrand(Brand brand) throws NonexistentEntityException, Exception {
        try {
            Query<Establishment> q = ds.createQuery(Establishment.class).filter("brand =", brand);
            List<Establishment> list = q.asList();
            if (list.isEmpty()) {
                throw new NonexistentEntityException("Not exist establishments with the brand '"
                        + brand.getBrandName() + "' .");
            } else {
                return list;
            }
        } catch (Exception e) {
            throw e;
        }
    }
    
    public Establishment findById(ObjectId id) throws NonexistentEntityException, Exception {
        try {
            Query q = ds.createQuery(Establishment.class).field("id").equal(id);
            if (q.countAll() == 0) {
                throw new NonexistentEntityException("The establishment with id '"
                        + id.toString() + "' couldn't be find. May no longer exist");
            } else {
                Establishment br = (Establishment) q.get();
                return br;
            }
        } catch (Exception e) {
            throw e;
        }
    }
}
